/*
 *  Copyright 2019-2020 Zheng Jie
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.fzhucc.modules.expert.service;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.shaded.com.google.gson.Gson;
import com.fzhucc.config.FileProperties;
import com.fzhucc.exception.BadRequestException;
import com.fzhucc.modules.activity.domain.dto.ActivityQueryCriteria;
import com.fzhucc.modules.displayMap.domain.dto.DisplayMapQueryCriteria;
import com.fzhucc.modules.expert.domain.Expert;
import com.fzhucc.modules.expert.domain.ExpertTag;
import com.fzhucc.modules.expert.domain.dto.*;
import com.fzhucc.modules.expert.repository.ExpertRepository;
import com.fzhucc.modules.expert.repository.ExpertTagRepository;
import com.fzhucc.modules.expert.service.mapstruct.ExpertMapper;
import com.fzhucc.modules.security.config.bean.LoginProperties;
import com.fzhucc.modules.security.config.bean.SecurityProperties;
import com.fzhucc.modules.security.domain.OnlineUser;
import com.fzhucc.modules.security.domain.bo.WxAuthenticationToken;
import com.fzhucc.modules.security.domain.dto.AuthDto;
import com.fzhucc.modules.security.domain.dto.JwtUserDto;
import com.fzhucc.modules.security.security.TokenProvider;
import com.fzhucc.modules.security.service.AuthenticationService;
import com.fzhucc.modules.security.service.OnlineUserService;
import com.fzhucc.modules.security.service.UserDetailsServiceImpl;
import com.fzhucc.modules.system.domain.Role;
import com.fzhucc.modules.system.domain.User;
import com.fzhucc.modules.system.repository.RoleRepository;
import com.fzhucc.modules.system.repository.UserRepository;
import com.fzhucc.modules.system.service.DictDetailService;
import com.fzhucc.modules.system.service.DictService;
import com.fzhucc.modules.system.service.UserService;
import com.fzhucc.modules.system.service.dto.DictDetailDto;
import com.fzhucc.modules.system.service.dto.DictDto;
import com.fzhucc.modules.system.service.dto.DictQueryCriteria;
import com.fzhucc.modules.system.service.dto.UserDto;
import com.fzhucc.utils.*;
import lombok.RequiredArgsConstructor;
import org.jeecg.pms.entity.PmsProject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import oshi.driver.mac.net.NetStat;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;

import static com.fzhucc.modules.expert.domain.ExpertTag.LABEL_BUSINESS_EXPERTISE;
import static com.fzhucc.modules.expert.domain.ExpertTag.LABEL_FAMILIAR_SPECIALTY;

/**
 * @author yyg
 * @website https://eladmin.vip
 * @description 服务实现
 * @date 2022-11-15
 **/
@Service
@RequiredArgsConstructor
public class ExpertService {

    private final UserService userService;

    private final RoleRepository roleRepository;

    private final ExpertRepository expertRepository;

    private final ExpertTagRepository expertTagRepository;
    private final ExpertMapper expertMapper;

    private final FileProperties properties;

    private final DictService dictService;

    private final RedisUtils redisUtils;

    private final DictDetailService dictDetailService;

    private final AuthenticationService authenticationService;

    private final WxClient wxClient;

    private final TokenProvider tokenProvider;

    private final OnlineUserService onlineUserService;

    private final UserRepository userRepository;

    private final SecurityProperties securityProperties;

    private final UserDetailsServiceImpl userDetailsService;

    @Value("${org.area.all}")
    public String all;

    @Value("${org.area.all2}")
    public String all2;

    @Value("${org.area.fz}")
    public String fz;

    @Value("${xf.add.url}")
    public String xfurl;

    @Value("${xf.edit.url}")
    public String xfediturl;

    @Value("${xf.thaw.url}")
    public String xfthawurl;

    @Value("${xf.freeze.url}")
    public String xffreezeurl;

    @Value("${xf.select.url}")
    public String xfselecturl;
    @Resource
    private LoginProperties loginProperties;

    public Map<String, Object> queryAll(ExpertQueryCriteria criteria, Pageable pageable) {
        if(criteria.getOrgArea()!=null && !criteria.getOrgArea().equals("")){
            //h5的直接传orgArea
            if (criteria.getOrgArea().equals(all)){
                criteria.setOrgArea(null);
            }
        }else{
            //管理端根据登录用户地区
            criteria.setOrgArea(setCriteria(criteria));
        }
        Page<Expert> page = expertRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
        Page<ExpertDto> map = page.map(expertMapper::toDto);
        List<ExpertDto> list = map.getContent();
        if (list != null) {
            for (ExpertDto expertDto : list) {
                List<ExpertTag> list2 = expertTagRepository.findByExpertId(expertDto.getId());
                List<String> res1 = new ArrayList<>();
                List<String> res2 = new ArrayList<>();
                List<ExpertTag> listBusinessExpertise = expertTagRepository.findByExpertIdWithType(expertDto.getId(), LABEL_BUSINESS_EXPERTISE);//业务特长
                List<ExpertTag> listFamiliarSpecialty = expertTagRepository.findByExpertIdWithType(expertDto.getId(), LABEL_FAMILIAR_SPECIALTY);//熟悉专业
                if (listBusinessExpertise != null && listBusinessExpertise.size() > 0) {
                    for (ExpertTag expertTag : listBusinessExpertise) {
                        res1.add(expertTag.getLabel());
                    }
                }
                if (listFamiliarSpecialty != null && listFamiliarSpecialty.size() > 0) {
                    for (ExpertTag expertTag : listFamiliarSpecialty) {
                        res2.add(expertTag.getLabel());
                    }
                }
                expertDto.setListBusinessExpertiseLabel(res1);//专家业务特长label
                expertDto.setListFamiliarSpecialtyLabel(res2);//专家熟悉专业label
            }
        }
        Map<String, Object> result = PageUtil.toPage(map);
        return result;
    }

    //根据不同设置不同的部门查看 处理  福建省;  或者  福建省;福州市;   或者 福建省;福州市;马尾区; 这种类型
    public String setCriteria(ExpertQueryCriteria criteria) {
        Long userId = null;
        try {
            userId = SecurityUtils.getCurrentUserId();
        } catch (Exception e) {
            String orgArea = criteria.getOrgArea();
            if (orgArea != null && orgArea.equals(all)) { //如果等于福建省则查全部
                return null;
            } else {
                return orgArea;
            }
        }
        if (userId != null) {
            Optional<User> userOptional = userRepository.findById(userId);
            User res = userOptional.get();
            if (res.getOrgArea() != null && (res.getOrgArea().equals(all) || res.getOrgArea().equals(all2))) {//包含福建省 则查全部
                return null;
            } else {
                if (res.getOrgArea() == null || res.getOrgArea().equals("")) {
                    //不赋予则返回所有都能看
                    return null;
                }
                if (res.getOrgArea().contains(";")) {
                    String[] split = res.getOrgArea().split(";");
                    if (split.length == 2) {
                        return split[1];
                    } else if (split.length == 3) {
                        return split[2];
                    } else if (split.length == 1) {
                        return split[0];
                    } else {
                        throw new BadRequestException("未符合规范的地区区域");
                    }
                } else {
                    throw new BadRequestException("未符合规范的地区区域");
                }
            }
        } else {
            throw new BadRequestException("用户ID未找到");
        }
    }

    public String orgAreaReturn() {
        Long userId = SecurityUtils.getCurrentUserId();
        if (userId == null) {//未登录则外面传进来
            return "";
        } else {
            Optional<User> userOptional = userRepository.findById(userId);
            User res = userOptional.get();
            if (res.getOrgArea() == null || res.getOrgArea().equals("")) {
                //不赋予则返回所有都能看
                return null;
            }
            if (res.getOrgArea().contains(";")) {
                String[] split = res.getOrgArea().split(";");
                if (split.length == 2) {
                    return split[1];
                } else if (split.length == 3) {
                    return split[1];
                } else if (split.length == 1) {
                    return split[0];
                } else {
                    throw new BadRequestException("未符合规范的地区区域");
                }
            } else {
                throw new BadRequestException("未符合规范的地区区域");
            }
        }
    }

    //获取福州大赛系统
    public PageImpl<Expert> getSciFuZhou(Pageable pageable, List<Expert> alls) {
        String result = HttpUtils2.get(xfselecturl);
        JSONObject jsonObject = JSONObject.parseObject(result);
        String code = jsonObject.get("code").toString();
        if (!code.equals("200")) {
            throw new BadRequestException("福州大赛数据获取失败");
        }
        Object str = jsonObject.get("result");
        ParseJsonArray parseJsonArray = new ParseJsonArray();
        //List<ExpertSciDto> list = parseJsonArray.parseJsonExpertArray(str.toString());//获取的大赛list
        List<Expert> list = parseJsonArray.parseJsonExpertArray(str.toString());//获取的大赛list

        list.addAll(alls);//合并获取的list

        //list.addAll(alls);

        //创建一个pageable对象
        //Pageable pageable = PageRequest.of(1, 10);
        //需要转换的list
        //List<实体类名称> distinctCollect
        //转换为page<>形式
        int start = pageable.getPageNumber() * pageable.getPageSize();
        int end = Math.min(start + pageable.getPageSize(), list.size());
        //PageImpl<ExpertSciDto> page = new PageImpl<>(list.subList(start, end), pageable, list.size());
        PageImpl<Expert> page = new PageImpl<>(list.subList(start, end), pageable, list.size());
        /*Page<ExpertSciDto> map = page.map(ExpertSci::toDto);
        PageUtil.toPage(map);*/
        //Map<String, Object> map = PageUtil.toPage(page);
        return page;
    }

    public Map<String, Object> queryExpertWithRaceWithOutPull(ExpertQueryCriteria criteria, Pageable pageable) {
        List<Expert> alls = expertRepository.findAlls();
        //获取大赛
        PageImpl<Expert> page = getSciFuZhou(pageable, alls);
        //Page<Expert> page = expertRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
        //Page<ExpertDto> map = page.map(expertMapper::toDto);
        Page<ExpertDto> map = page.map(expertMapper::toDto);
        List<ExpertDto> list = map.toList();
        if (list != null) {
            for (ExpertDto expertDto : list) {
                if (expertDto.getId() != null) {
                    List<ExpertTag> list2 = expertTagRepository.findByExpertId(expertDto.getId());
                    List<String> res1 = new ArrayList<>();
                    List<String> res2 = new ArrayList<>();
                    List<ExpertTag> listBusinessExpertise = expertTagRepository.findByExpertIdWithType(expertDto.getId(), LABEL_BUSINESS_EXPERTISE);//业务特长
                    List<ExpertTag> listFamiliarSpecialty = expertTagRepository.findByExpertIdWithType(expertDto.getId(), LABEL_FAMILIAR_SPECIALTY);//熟悉专业
                    if (listBusinessExpertise != null && listBusinessExpertise.size() > 0) {
                        for (ExpertTag expertTag : listBusinessExpertise) {
                            res1.add(expertTag.getLabel());
                        }
                    }
                    if (listFamiliarSpecialty != null && listFamiliarSpecialty.size() > 0) {
                        for (ExpertTag expertTag : listFamiliarSpecialty) {
                            res2.add(expertTag.getLabel());
                        }
                    }
                    expertDto.setListBusinessExpertiseLabel(res1);//专家业务特长label
                    expertDto.setListFamiliarSpecialtyLabel(res2);//专家熟悉专业label
                }
            }
        }
        return PageUtil.toPage(map);
    }

    public Boolean getFzSciExpert() {
        return getSciFuZhouInExpert(true);
    }

    @Transactional
    public String distributeExpert(ExpertDtoList expertDtoList) {
        //发送数据给大赛 实行下发操作
        if (expertDtoList == null) {
            throw new BadRequestException("下发数据为null无法操作");
        }
        List<ExpertDto> list = expertDtoList.getList();
        if (list == null) {
            throw new BadRequestException("下发数据为null无法操作");
        }
        if (list.size() < 0) {
            throw new BadRequestException("下发数据集合小于零无法操作");
        }
        if (expertDtoList.getType() == null) {
            throw new BadRequestException("缺少下发数据类型");
        }
        if (expertDtoList.getType().equals("")) {
            throw new BadRequestException("缺少下发数据类型");
        }
        if (expertDtoList.getType().equals("福州三创大赛") || expertDtoList.getType().equals("其他")) {

        } else {
            throw new BadRequestException("下发数据类型不匹配");
        }
        String xftype = expertDtoList.getType();
        for (ExpertDto expertDto : list) {
            if (expertDto.getIsPull() != null && expertDto.getIsPull() == 1) {
                throw new BadRequestException(expertDto.getRealname() + ",该数据为下发数据无法操作");
            }
        }
        List<Integer> kcIds = new ArrayList<Integer>();
        List<Integer> kcIdsDongjie = new ArrayList<Integer>();
        List<Integer> kcIdsJieDong = new ArrayList<Integer>();
        ExpertDtoToSci expertDtoToSci = new ExpertDtoToSci();
        List<ExpertSendSciDto> newList = new ArrayList<ExpertSendSciDto>();
        for (ExpertDto expertDto : list) {
            ExpertSendSciDto expertSendSciDto = new ExpertSendSciDto();
            expertSendSciDto.setKcId(expertDto.getId());
            kcIds.add(expertDto.getId());
            expertSendSciDto.setUsername(expertDto.getUsername());
            expertSendSciDto.setRealname(expertDto.getRealname());
            expertSendSciDto.setAvatar(expertDto.getAvatar());
            expertSendSciDto.setPhone(expertDto.getPhone());
            expertSendSciDto.setEmail(expertDto.getEmail());
            expertSendSciDto.setIsAcademician(expertDto.getIsAcademician());
            expertSendSciDto.setUserIntro(expertDto.getUserIntro());
            Timestamp birthday = expertDto.getBirthday();
            if (birthday != null) {
                Date date = new Date(birthday.getTime());
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String mytime = sdf.format(date);
                expertSendSciDto.setBirthday(mytime);
            }
            expertSendSciDto.setMajor(expertDto.getMajor());
            expertSendSciDto.setHospital(expertDto.getHospital());
            expertSendSciDto.setUnit(expertDto.getUnit());
            expertSendSciDto.setPostStr(expertDto.getPostStr());
            expertSendSciDto.setRemarks(expertDto.getRemarks());
            expertSendSciDto.setStatus(expertDto.getSciStatus());
            if (expertSendSciDto.getStatus() != null) {
                if (expertSendSciDto.getStatus() == 1) {//正常
                    kcIdsJieDong.add(expertDto.getId());
                }
                if (expertSendSciDto.getStatus() == 2) {//冻结
                    kcIdsDongjie.add(expertDto.getId());
                }
            } else {//默认设置为正常
                kcIdsJieDong.add(expertDto.getId());
            }
            newList.add(expertSendSciDto);
        }
        expertDtoToSci.setList(newList);
        Gson gson = new Gson();
        String str = gson.toJson(expertDtoToSci);
        String result = HttpUtils2.post(xfurl, str);
        JSONObject jsonObject = JSONObject.parseObject(result);
        /*Integer code = Integer.parseInt(jsonObject.get("code").toString());
        if (code != 200) {
            throw new BadRequestException("下发请求大赛数据失败");
        }*/
        Integer code = Integer.parseInt(jsonObject.get("code").toString());
        if (code == 200) {
            if (xftype.equals("福州三创大赛")) {
                if (kcIds != null && kcIds.size() > 0) {//说明同步成功则改科创数据库里 下发字段
                    for (Integer id : kcIds) {
                        Optional<Expert> res = expertRepository.findById(id);
                        if (res.isPresent()) {
                            Expert expert = res.get();
                            String xf = expert.getXf();
                            if (xf != null && !xf.equals("")) {
                                if (xf.contains(";")) {
                                    String str2 = xf + "福州三创大赛;";
                                    expert.setXf(str2);
                                } else {
                                    String str3 = xf + ";福州三创大赛;";
                                    expert.setXf(str3);
                                }
                            } else {
                                expert.setXf("福州三创大赛");
                            }
                        }
                    }
                }
                if (kcIdsJieDong != null && kcIdsJieDong.size() > 0) {
                    for (Integer id : kcIdsJieDong) {
                        Optional<Expert> res = expertRepository.findById(id);
                        if (res.isPresent()) {
                            Expert expert = res.get();
                            expert.setSciStatus(1);
                            expertRepository.save(expert);
                        }
                    }
                }
                if (kcIdsDongjie != null && kcIdsDongjie.size() > 0) {
                    for (Integer id : kcIdsDongjie) {
                        Optional<Expert> res = expertRepository.findById(id);
                        if (res.isPresent()) {
                            Expert expert = res.get();
                            expert.setSciStatus(2);
                            expertRepository.save(expert);
                        }
                    }
                }
            }
            if (xftype.equals("其他")) {
                if (kcIds != null && kcIds.size() > 0) {//说明同步成功则改科创数据库里 下发字段
                    for (Integer id : kcIds) {
                        Optional<Expert> res = expertRepository.findById(id);
                        if (res.isPresent()) {
                            Expert expert = res.get();
                            String xf = expert.getXf();
                            if (xf != null && !xf.equals("") && xf.contains(";")) {
                                if (xf.contains(";")) {
                                    String str2 = xf + "其他;";
                                    expert.setXf(str2);
                                } else {
                                    String str3 = xf + ";其他;";
                                    expert.setXf(str3);
                                }
                            } else {
                                expert.setXf("其他");
                            }
                        }
                    }
                }
                if (kcIdsJieDong != null && kcIdsJieDong.size() > 0) {
                    for (Integer id : kcIdsJieDong) {
                        Optional<Expert> res = expertRepository.findById(id);
                        if (res.isPresent()) {
                            Expert expert = res.get();
                            expert.setSciStatus(1);
                            expertRepository.save(expert);
                        }
                    }
                }
                if (kcIdsDongjie != null && kcIdsDongjie.size() > 0) {
                    for (Integer id : kcIdsDongjie) {
                        Optional<Expert> res = expertRepository.findById(id);
                        if (res.isPresent()) {
                            Expert expert = res.get();
                            expert.setSciStatus(2);
                            expertRepository.save(expert);
                        }
                    }
                }
            }
        }
        Object message = jsonObject.get("message");
        return message.toString();
    }

    public String editDistributeExpert(ExpertDtoList expertDtoList) {
        //发送数据给大赛 实行下发编辑操作
        if (expertDtoList == null) {
            throw new BadRequestException("下发数据为null无法操作");
        }
        List<ExpertDto> list = expertDtoList.getList();
        if (list == null) {
            throw new BadRequestException("下发数据为null无法操作");
        }
        if (list.size() < 0) {
            throw new BadRequestException("下发数据集合小于零无法操作");
        }
        for (ExpertDto expertDto : list) {
            if (expertDto.getIsPull() != null && expertDto.getIsPull() == 1) {
                throw new BadRequestException(expertDto.getRealname() + ",该数据为下发数据无法操作");
            }
        }
        ExpertDtoToSci expertDtoToSci = new ExpertDtoToSci();
        List<ExpertSendSciDto> newList = new ArrayList<ExpertSendSciDto>();
        for (ExpertDto expertDto : list) {
            ExpertSendSciDto expertSendSciDto = new ExpertSendSciDto();
            expertSendSciDto.setKcId(expertDto.getId());
            expertSendSciDto.setUsername(expertDto.getUsername());
            expertSendSciDto.setRealname(expertDto.getRealname());
            expertSendSciDto.setAvatar(expertDto.getAvatar());
            expertSendSciDto.setPhone(expertDto.getPhone());
            expertSendSciDto.setEmail(expertDto.getEmail());
            expertSendSciDto.setIsAcademician(expertDto.getIsAcademician());
            expertSendSciDto.setUserIntro(expertDto.getUserIntro());
            Timestamp birthday = expertDto.getBirthday();
            if (birthday != null) {
                Date date = new Date(birthday.getTime());
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String mytime = sdf.format(date);
                expertSendSciDto.setBirthday(mytime);
            }
            expertSendSciDto.setMajor(expertDto.getMajor());
            expertSendSciDto.setHospital(expertDto.getHospital());
            expertSendSciDto.setUnit(expertDto.getUnit());
            expertSendSciDto.setPostStr(expertDto.getPostStr());
            expertSendSciDto.setRemarks(expertDto.getRemarks());
            expertSendSciDto.setStatus(expertDto.getSciStatus());
            newList.add(expertSendSciDto);
        }
        expertDtoToSci.setList(newList);
        Gson gson = new Gson();
        String str = gson.toJson(expertDtoToSci);
        String result = HttpUtils2.post(xfediturl, str);
        JSONObject jsonObject = JSONObject.parseObject(result);
        /*Integer code = Integer.parseInt(jsonObject.get("code").toString());
        if (code != 200) {
            throw new BadRequestException("下发请求编辑大赛数据失败");
        }*/
        Object message = jsonObject.get("message");
        return message.toString();
    }


    @Transactional
    public String freezeDistributeExpert(ExpertDtoList expertDtoList) {
        //发送数据给大赛 实行下发冻结操作
        if (expertDtoList == null) {
            throw new BadRequestException("下发冻结数据为null无法操作");
        }
        List<ExpertDto> list = expertDtoList.getList();
        if (list == null) {
            throw new BadRequestException("下发冻结数据为null无法操作");
        }
        if (list.size() < 0) {
            throw new BadRequestException("下发冻结数据集合小于零无法操作");
        }
        for (ExpertDto expertDto : list) {
            if (expertDto.getIsPull() != null && expertDto.getIsPull() == 1) {
                throw new BadRequestException(expertDto.getRealname() + ",该数据为下发数据无法操作");
            }
        }
        List<Integer> kcIds = new ArrayList<Integer>();
        ExpertDtoToSci expertDtoToSci = new ExpertDtoToSci();
        List<ExpertSendSciDto> newList = new ArrayList<ExpertSendSciDto>();
        for (ExpertDto expertDto : list) {
            ExpertSendSciDto expertSendSciDto = new ExpertSendSciDto();
            expertSendSciDto.setKcId(expertDto.getId());
            newList.add(expertSendSciDto);
            kcIds.add(expertDto.getId());
        }
        expertDtoToSci.setList(newList);
        Gson gson = new Gson();
        String str = gson.toJson(expertDtoToSci);
        String result = HttpUtils2.post(xffreezeurl, str);
        JSONObject jsonObject = JSONObject.parseObject(result);
        Integer code = Integer.parseInt(jsonObject.get("code").toString());
        if (code == 200) {
            //更新表中冻结操作
            if (kcIds != null && kcIds.size() > 0) {
                for (Integer id : kcIds) {
                    Optional<Expert> res = expertRepository.findById(id);
                    if (res.isPresent()) {
                        Expert expert = res.get();
                        expert.setSciStatus(2);
                        expertRepository.save(expert);
                    }
                }
            }
        }

        Object message = jsonObject.get("message");
        return message.toString();
    }

    @Transactional
    public String thawDistributeExpert(ExpertDtoList expertDtoList) {
        //发送数据给大赛 实行下发解冻操作
        if (expertDtoList == null) {
            throw new BadRequestException("下发解冻数据为null无法操作");
        }
        List<ExpertDto> list = expertDtoList.getList();
        if (list == null) {
            throw new BadRequestException("下发解冻数据为null无法操作");
        }
        if (list.size() < 0) {
            throw new BadRequestException("下发解冻数据集合小于零无法操作");
        }
        for (ExpertDto expertDto : list) {
            if (expertDto.getIsPull() != null && expertDto.getIsPull() == 1) {
                throw new BadRequestException(expertDto.getRealname() + ",该数据为下发数据无法操作");
            }
        }
        List<Integer> kcIds = new ArrayList<Integer>();
        ExpertDtoToSci expertDtoToSci = new ExpertDtoToSci();
        List<ExpertSendSciDto> newList = new ArrayList<ExpertSendSciDto>();
        for (ExpertDto expertDto : list) {
            ExpertSendSciDto expertSendSciDto = new ExpertSendSciDto();
            expertSendSciDto.setKcId(expertDto.getId());
            newList.add(expertSendSciDto);
            kcIds.add(expertDto.getId());
        }
        expertDtoToSci.setList(newList);
        Gson gson = new Gson();
        String str = gson.toJson(expertDtoToSci);
        String result = HttpUtils2.post(xfthawurl, str);
        JSONObject jsonObject = JSONObject.parseObject(result);
        Integer code = Integer.parseInt(jsonObject.get("code").toString());
        if (code == 200) {
            //更新表中冻结操作
            if (kcIds != null && kcIds.size() > 0) {
                for (Integer id : kcIds) {
                    Optional<Expert> res = expertRepository.findById(id);
                    if (res.isPresent()) {
                        Expert expert = res.get();
                        expert.setSciStatus(1);
                        expertRepository.save(expert);
                    }
                }
            }
        }
        Object message = jsonObject.get("message");
        return message.toString();
    }

    public Map<String, Object> queryExpertDistribute(ExpertQueryCriteria criteria, Pageable pageable) {
        Page<Expert> page = expertRepository.findAllsWithPage(pageable);
        //Page<Expert> page = expertRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
        Page<ExpertDto> map = page.map(expertMapper::toDto);
        List<ExpertDto> list = map.getContent();
        if (list != null) {
            for (ExpertDto expertDto : list) {
                List<ExpertTag> list2 = expertTagRepository.findByExpertId(expertDto.getId());
                List<String> res1 = new ArrayList<>();
                List<String> res2 = new ArrayList<>();
                List<ExpertTag> listBusinessExpertise = expertTagRepository.findByExpertIdWithType(expertDto.getId(), LABEL_BUSINESS_EXPERTISE);//业务特长
                List<ExpertTag> listFamiliarSpecialty = expertTagRepository.findByExpertIdWithType(expertDto.getId(), LABEL_FAMILIAR_SPECIALTY);//熟悉专业
                if (listBusinessExpertise != null && listBusinessExpertise.size() > 0) {
                    for (ExpertTag expertTag : listBusinessExpertise) {
                        res1.add(expertTag.getLabel());
                    }
                }
                if (listFamiliarSpecialty != null && listFamiliarSpecialty.size() > 0) {
                    for (ExpertTag expertTag : listFamiliarSpecialty) {
                        res2.add(expertTag.getLabel());
                    }
                }
                expertDto.setListBusinessExpertiseLabel(res1);//专家业务特长label
                expertDto.setListFamiliarSpecialtyLabel(res2);//专家熟悉专业label
            }
        }
        Map<String, Object> result = PageUtil.toPage(map);
        return result;
    }

    public Map<String, Object> queryExpertShowFreeze(ExpertQueryCriteria criteria, Pageable pageable) {
        //TODO同步操作 不用
        /*List<Expert> allsPull = expertRepository.findAllsPull();
        if (allsPull != null && allsPull.size() > 0) {
        }else{
            getSciFuZhouInExpert(true);
        }*/

        Page<Expert> page = expertRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
        Page<ExpertDto> map = page.map(expertMapper::toDto);
        List<ExpertDto> list = map.getContent();
        if (list != null) {
            for (ExpertDto expertDto : list) {
                List<ExpertTag> list2 = expertTagRepository.findByExpertId(expertDto.getId());
                List<String> res1 = new ArrayList<>();
                List<String> res2 = new ArrayList<>();
                List<ExpertTag> listBusinessExpertise = expertTagRepository.findByExpertIdWithType(expertDto.getId(), LABEL_BUSINESS_EXPERTISE);//业务特长
                List<ExpertTag> listFamiliarSpecialty = expertTagRepository.findByExpertIdWithType(expertDto.getId(), LABEL_FAMILIAR_SPECIALTY);//熟悉专业
                if (listBusinessExpertise != null && listBusinessExpertise.size() > 0) {
                    for (ExpertTag expertTag : listBusinessExpertise) {
                        res1.add(expertTag.getLabel());
                    }
                }
                if (listFamiliarSpecialty != null && listFamiliarSpecialty.size() > 0) {
                    for (ExpertTag expertTag : listFamiliarSpecialty) {
                        res2.add(expertTag.getLabel());
                    }
                }
                expertDto.setListBusinessExpertiseLabel(res1);//专家业务特长label
                expertDto.setListFamiliarSpecialtyLabel(res2);//专家熟悉专业label
            }
        }
        Map<String, Object> result = PageUtil.toPage(map);
        return result;
    }

    public Map<String, Object> queryExpertWithRaceAndIn(ExpertQueryCriteria criteria, Pageable pageable) {
        //TODO同步操作 不用
        /*List<Expert> allsPull = expertRepository.findAllsPull();
        if (allsPull != null && allsPull.size() > 0) {
        }else{
            getSciFuZhouInExpert(true);
        }*/

        Page<Expert> page = expertRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
        Page<ExpertDto> map = page.map(expertMapper::toDto);
        List<ExpertDto> list = map.getContent();
        if (list != null) {
            for (ExpertDto expertDto : list) {
                List<ExpertTag> list2 = expertTagRepository.findByExpertId(expertDto.getId());
                List<String> res1 = new ArrayList<>();
                List<String> res2 = new ArrayList<>();
                List<ExpertTag> listBusinessExpertise = expertTagRepository.findByExpertIdWithType(expertDto.getId(), LABEL_BUSINESS_EXPERTISE);//业务特长
                List<ExpertTag> listFamiliarSpecialty = expertTagRepository.findByExpertIdWithType(expertDto.getId(), LABEL_FAMILIAR_SPECIALTY);//熟悉专业
                if (listBusinessExpertise != null && listBusinessExpertise.size() > 0) {
                    for (ExpertTag expertTag : listBusinessExpertise) {
                        res1.add(expertTag.getLabel());
                    }
                }
                if (listFamiliarSpecialty != null && listFamiliarSpecialty.size() > 0) {
                    for (ExpertTag expertTag : listFamiliarSpecialty) {
                        res2.add(expertTag.getLabel());
                    }
                }
                expertDto.setListBusinessExpertiseLabel(res1);//专家业务特长label
                expertDto.setListFamiliarSpecialtyLabel(res2);//专家熟悉专业label
            }
        }
        Map<String, Object> result = PageUtil.toPage(map);
        return result;
    }


    @Transactional
    //获取福州大赛系统并专家表入库
    public Boolean getSciFuZhouInExpert(boolean isIn) {
        if (isIn) {
            String result = HttpUtils2.get(xfselecturl);
            JSONObject jsonObject = JSONObject.parseObject(result);
            Object message = jsonObject.get("message");
            String code = jsonObject.get("code").toString();
            if (!code.equals("200")) {
                throw new BadRequestException(message.toString());
                //throw new BadRequestException("福州大赛专家数据获取失败");
            }
            Object str = jsonObject.get("result");
            ParseJsonArray parseJsonArray = new ParseJsonArray();
            List<Expert> list = parseJsonArray.parseJsonExpertArray(str.toString());//获取的大赛list
            if (list != null && list.size() > 0) {
                for (Expert expert : list) {
                    String rexpertid = expert.getRexpertid();//根据大赛id 查有的话编辑 没有的话新增
                    Expert res = expertRepository.findByRSciId(rexpertid);
                    if (res == null) {
                        expertRepository.save(expert);
                    } else {
                        res.setUsername(expert.getUsername());
                        res.setRealname(expert.getRealname());
                        res.setAvatar(expert.getAvatar());
                        res.setPhone(expert.getPhone());
                        res.setEmail(expert.getEmail());
                        res.setIsAcademician(expert.getIsAcademician());
                        res.setUserIntro(expert.getUserIntro());
                        res.setBirthday(expert.getBirthday());
                        res.setMajor(expert.getMajor());
                        res.setHospital(expert.getHospital());
                        res.setUnit(expert.getUnit());
                        res.setPostStr(expert.getPostStr());
                        res.setRemarks(expert.getRemarks());
                        res.setSource(expert.getSource());
                        res.setIsShow(expert.getIsShow());
                        res.setOrgArea(fz);
                        res.setIsDelete(expert.getIsDelete());
                        res.setIsPush(expert.getIsPush());
                        res.setType(expert.getType());
                        res.setPlate(expert.getPlate());//所属平台
                        res.setSort(expert.getSort());//固定排序
                        res.setIsPull(expert.getIsPull());//是下发
                        expertRepository.save(res);
                    }
                }
                return true;
            }
            return false;
        }
        return false;
    }

    public List<ExpertDto> queryAll(ExpertQueryCriteria criteria) {
        if(criteria.getOrgArea()!=null && !criteria.getOrgArea().equals("")){
            //h5的直接传orgArea
            if (criteria.getOrgArea().equals(all)){
                criteria.setOrgArea(null);
            }
        }else{
            //管理端根据登录用户地区
            criteria.setOrgArea(setCriteria(criteria));
        }
        return expertMapper.toDto(expertRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder)));
    }

    public ExpertDto findById(Integer id) {
        Expert expert = expertRepository.findById(id).orElseGet(Expert::new);
        ValidationUtil.isNull(expert.getId(), "Expert", "id", id);
        return expertMapper.toDto(expert);
    }

    @Transactional
    public void registExpertUser(Expert expert) {
        boolean flag1 = true;
        boolean flag2 = true;
        String username = expert.getUsername();
        String phone = expert.getPhone();
        if (username == null || username.equals("")) {
            flag1 = false;
        }
        if (phone == null || phone.equals("")) {
            flag2 = false;
        }
        if (flag2 && flag1) { //说明都不为空
            User user1 = userRepository.findByPhone(phone);
            User byUsername = userRepository.findByUsername(username);
            if (user1 == null && byUsername == null) {
                User user = new User();
                user.setUsername(expert.getUsername());
                user.setNickName(expert.getRealname());
                user.setPhone(expert.getPhone());
                //user.setEmail(expert.getEmail());
                user.setAvatarName(expert.getAvatar());
                user.setAvatarPath(expert.getAvatar());
                user.setPassword("$2a$10$GViTa5x2WfPHPsAivKMq7uZM.PB1bEvvUPFlvXY/C3oBa17LnixJ2");//123456
                user.setIsAdmin(false);
                user.setEnabled(true);
                user.setCreateBy("System");
                user.setUpdateBy("System");
                user.setCreateTime(new Timestamp(new Date().getTime()));
                user.setUpdateTime(new Timestamp(new Date().getTime()));
                Long a = 4L;
                user.setType(a);//专家
                Role expertRole = roleRepository.findByName("专家");
                if (expertRole != null) {
                    Set<Role> set = new HashSet<Role>();
                    set.add(expertRole);
                    user.setRoles(set);
                }
                userRepository.save(user);
            }
        }
        if (flag1){
            if (!flag2){
                //只有用户名的情况
                User byUsername = userRepository.findByUsername(username);
                if (byUsername == null) {
                    User user = new User();
                    user.setUsername(expert.getUsername());
                    user.setNickName(expert.getRealname());
                    user.setPhone(expert.getPhone());
                    //user.setEmail(expert.getEmail());
                    user.setAvatarName(expert.getAvatar());
                    user.setAvatarPath(expert.getAvatar());
                    user.setPassword("$2a$10$GViTa5x2WfPHPsAivKMq7uZM.PB1bEvvUPFlvXY/C3oBa17LnixJ2");//123456
                    user.setIsAdmin(false);
                    user.setEnabled(true);
                    user.setCreateBy("System");
                    user.setUpdateBy("System");
                    user.setCreateTime(new Timestamp(new Date().getTime()));
                    user.setUpdateTime(new Timestamp(new Date().getTime()));
                    Long a = 4L;
                    user.setType(a);//专家
                    Role expertRole = roleRepository.findByName("专家");
                    if (expertRole != null) {
                        Set<Role> set = new HashSet<Role>();
                        set.add(expertRole);
                        user.setRoles(set);
                    }
                    userRepository.save(user);
                }
            }
        }

        if (flag2){
            if (!flag1){
                //只有手机号的情况
                User user1 = userRepository.findByPhone(phone);
                if (user1 == null) {
                    User user = new User();
                    user.setUsername(expert.getPhone());
                    user.setNickName(expert.getRealname());
                    user.setPhone(expert.getPhone());
                    //user.setEmail(expert.getEmail());
                    user.setAvatarName(expert.getAvatar());
                    user.setAvatarPath(expert.getAvatar());
                    user.setPassword("$2a$10$GViTa5x2WfPHPsAivKMq7uZM.PB1bEvvUPFlvXY/C3oBa17LnixJ2");//123456
                    user.setIsAdmin(false);
                    user.setEnabled(true);
                    user.setCreateBy("System");
                    user.setUpdateBy("System");
                    user.setCreateTime(new Timestamp(new Date().getTime()));
                    user.setUpdateTime(new Timestamp(new Date().getTime()));
                    Long a = 4L;
                    user.setType(a);//专家
                    Role expertRole = roleRepository.findByName("专家");
                    if (expertRole != null) {
                        Set<Role> set = new HashSet<Role>();
                        set.add(expertRole);
                        user.setRoles(set);
                    }
                    userRepository.save(user);
                }
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public ExpertDto create(ExpertAddDto expertAddDto) {
        Expert resources = new Expert();
        Long userId = SecurityUtils.getCurrentUserId();
        if (userId == null) {
            throw new BadRequestException("用户ID未找到");
        }
        resources.setCreateUserId(userId);
        resources.setUsername(expertAddDto.getUsername());
        resources.setRealname(expertAddDto.getRealname());
        resources.setAvatar(expertAddDto.getAvatar());
        resources.setPhone(expertAddDto.getPhone());
        resources.setEmail(expertAddDto.getEmail());
        resources.setIsShow(expertAddDto.getIsShow());
        resources.setIsAcademician(expertAddDto.getIsAcademician());
        resources.setUserIntro(expertAddDto.getUserIntro());
        //前端传 年-月  补齐-日
        String str = expertAddDto.getBirthday();
        if (str != null && (!str.equals(""))) {
            String newstr = str + "-01 00:00:00";
            resources.setBirthday(Timestamp.valueOf(newstr));
        }

        resources.setMajor(expertAddDto.getMajor());
        resources.setHospital(expertAddDto.getHospital());
        resources.setUnit(expertAddDto.getUnit());
        resources.setPostStr(expertAddDto.getPostStr());
        resources.setRemarks(expertAddDto.getRemarks());
        resources.setSciStatus(expertAddDto.getSciStatus());
        resources.setType(expertAddDto.getType());
        resources.setSource(expertAddDto.getSource());
        resources.setUserId(expertAddDto.getUserId());
        resources.setIsDelete(0);
        resources.setIsPull(0);//默认无下发数据
        resources.setIsPush(expertAddDto.getIsPush());
        resources.setSort(expertAddDto.getSort());
        resources.setPlate("汇创榕城");//默认新增汇创榕城
        //调整为登录账号为哪个市的添加哪个市
        resources.setOrgArea(orgAreaReturn());
        resources.setCoachingEnterprises(expertAddDto.getCoachingEnterprises());
        Expert expert = expertRepository.save(resources);
        if (expert != null) {
            //注册成功则注册用户
            //TODO
            registExpertUser(expert);

            if (expertAddDto.getListBusinessExpertiseLabel() != null) {
                List<ExpertTag> tagList = expertTagRepository.findByExpertIdWithType(expert.getId(), LABEL_BUSINESS_EXPERTISE);//业务特长
                if (tagList != null && tagList.size() > 0) {
                    for (ExpertTag expertTag : tagList) {
                        expertTagRepository.deleteById(expertTag.getId());
                    }
                }
                List<String> listLabelWithType = expertAddDto.getListBusinessExpertiseLabel();
                for (String label : listLabelWithType) {
                    ExpertTag expertTag = new ExpertTag();
                    expertTag.setExpertId(expert.getId());
                    expertTag.setType(LABEL_BUSINESS_EXPERTISE);
                    expertTag.setLabel(label);
                    expertTagRepository.save(expertTag);
                }
            }
            if (expertAddDto.getListFamiliarSpecialtyLabel() != null) {
                List<ExpertTag> tagList = expertTagRepository.findByExpertIdWithType(expert.getId(), LABEL_FAMILIAR_SPECIALTY);//熟悉专业
                if (tagList != null && tagList.size() > 0) {
                    for (ExpertTag expertTag : tagList) {
                        expertTagRepository.deleteById(expertTag.getId());
                    }
                }
                List<String> listLabelWithType = expertAddDto.getListFamiliarSpecialtyLabel();
                for (String label : listLabelWithType) {
                    ExpertTag expertTag = new ExpertTag();
                    expertTag.setExpertId(expert.getId());
                    expertTag.setType(LABEL_FAMILIAR_SPECIALTY);
                    expertTag.setLabel(label);
                    expertTagRepository.save(expertTag);
                }
            }
        }
        ExpertDto expertDto = expertMapper.toDto(expert);
        List<String> res1 = new ArrayList<>();
        List<String> res2 = new ArrayList<>();
        List<ExpertTag> listBusinessExpertise = expertTagRepository.findByExpertIdWithType(expertDto.getId(), LABEL_BUSINESS_EXPERTISE);//业务特长
        List<ExpertTag> listFamiliarSpecialty = expertTagRepository.findByExpertIdWithType(expertDto.getId(), LABEL_FAMILIAR_SPECIALTY);//熟悉专业
        if (listBusinessExpertise != null && listBusinessExpertise.size() > 0) {
            for (ExpertTag expertTag : listBusinessExpertise) {
                res1.add(expertTag.getLabel());
            }
        }
        if (listFamiliarSpecialty != null && listFamiliarSpecialty.size() > 0) {
            for (ExpertTag expertTag : listFamiliarSpecialty) {
                res2.add(expertTag.getLabel());
            }
        }
        expertDto.setListBusinessExpertiseLabel(res1);//专家业务特长label
        expertDto.setListFamiliarSpecialtyLabel(res2);//专家熟悉专业label
        return expertDto;
    }

    @Transactional(rollbackFor = Exception.class)
    public void update(ExpertEditDto expertEditDto) {
        Expert resources = new Expert();
        Long userId = SecurityUtils.getCurrentUserId();
        if (userId == null) {
            throw new BadRequestException("用户ID未找到");
        }

        resources.setId(expertEditDto.getId());
        resources.setCreateUserId(userId);
        resources.setUsername(expertEditDto.getUsername());
        resources.setRealname(expertEditDto.getRealname());
        resources.setAvatar(expertEditDto.getAvatar());
        resources.setPhone(expertEditDto.getPhone());
        resources.setEmail(expertEditDto.getEmail());
        resources.setIsShow(expertEditDto.getIsShow());
        resources.setIsAcademician(expertEditDto.getIsAcademician());
        resources.setUserIntro(expertEditDto.getUserIntro());

        //前端传 年-月  补齐-日
        String str = expertEditDto.getBirthday();
        if (str != null && (!str.equals(""))) {
            String newstr = str + "-01 00:00:00";
            resources.setBirthday(Timestamp.valueOf(newstr));
        }
        resources.setMajor(expertEditDto.getMajor());
        resources.setHospital(expertEditDto.getHospital());
        resources.setUnit(expertEditDto.getUnit());
        resources.setPostStr(expertEditDto.getPostStr());
        resources.setRemarks(expertEditDto.getRemarks());
        resources.setType(expertEditDto.getType());
        resources.setSource(expertEditDto.getSource());
        resources.setUserId(expertEditDto.getUserId());
        resources.setIsDelete(expertEditDto.getIsDelete());
        resources.setSort(expertEditDto.getSort());
        resources.setIsPush(expertEditDto.getIsPush());
        resources.setSciStatus(expertEditDto.getSciStatus());
        //调整为登录账号为哪个市的添加哪个市
        resources.setOrgArea(orgAreaReturn());

        resources.setCoachingEnterprises(expertEditDto.getCoachingEnterprises());
        Expert expert = expertRepository.findById(resources.getId()).orElseGet(Expert::new);
        if (expert.getIsPull() != null && expert.getIsPull() == 1) {
            throw new BadRequestException("下发数据无法进行编辑操作");
        }
        ValidationUtil.isNull(expert.getId(), "Expert", "id", resources.getId());
        expert.copy(resources);
        Expert expert1 = expertRepository.save(expert);
        if (expert1 != null) {
            if (expertEditDto.getListBusinessExpertiseLabel() != null) {
                List<ExpertTag> tagList = expertTagRepository.findByExpertIdWithType(expert.getId(), LABEL_BUSINESS_EXPERTISE);//业务特长
                if (tagList != null && tagList.size() > 0) {
                    for (ExpertTag expertTag : tagList) {
                        expertTagRepository.deleteById(expertTag.getId());
                    }
                }
                List<String> listLabelWithType = expertEditDto.getListBusinessExpertiseLabel();
                for (String label : listLabelWithType) {
                    ExpertTag expertTag = new ExpertTag();
                    expertTag.setExpertId(expert.getId());
                    expertTag.setType(LABEL_BUSINESS_EXPERTISE);
                    expertTag.setLabel(label);
                    expertTagRepository.save(expertTag);
                }
            }
            if (expertEditDto.getListFamiliarSpecialtyLabel() != null) {
                List<ExpertTag> tagList = expertTagRepository.findByExpertIdWithType(expert.getId(), LABEL_FAMILIAR_SPECIALTY);//熟悉专业
                if (tagList != null && tagList.size() > 0) {
                    for (ExpertTag expertTag : tagList) {
                        expertTagRepository.deleteById(expertTag.getId());
                    }
                }
                List<String> listLabelWithType = expertEditDto.getListFamiliarSpecialtyLabel();
                for (String label : listLabelWithType) {
                    ExpertTag expertTag = new ExpertTag();
                    expertTag.setExpertId(expert.getId());
                    expertTag.setType(LABEL_FAMILIAR_SPECIALTY);
                    expertTag.setLabel(label);
                    expertTagRepository.save(expertTag);
                }
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void deleteAll(Integer[] ids) {
        for (Integer id : ids) {
            //expertRepository.deleteById(id);
            //设置删除状态为1
            Optional<Expert> res = expertRepository.findById(id);
            if (!res.isPresent()) {
                throw new BadRequestException("专家未找到");
            }
            Expert expert = res.get();
            if (expert.getIsPull() != null && expert.getIsPull() == 1) {
                throw new BadRequestException("下发数据无法进行删除操作");
            }
            expert.setIsDelete(1);
            expertRepository.save(expert);
        }
    }

    public void download(List<ExpertDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (ExpertDto expert : all) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("登录账号", expert.getUsername());
            map.put("真实姓名", expert.getRealname());
            map.put("头像", expert.getAvatar());
            map.put("手机号码", expert.getPhone());
            map.put("电子邮箱", expert.getEmail());
            map.put("是否小程序展示", expert.getIsShow());
            map.put("是否院士", expert.getIsAcademician());
            map.put("用户简介", expert.getUserIntro());
            map.put("出生日期", expert.getBirthday());
            map.put("专业", expert.getMajor());
            map.put("所在院", expert.getHospital());
            map.put("单位", expert.getUnit());
            map.put("职务", expert.getPostStr());
            map.put("备注", expert.getRemarks());
            map.put("专家类型", expert.getType());
            map.put("排序", expert.getSort());
            map.put("是否推送", expert.getIsPush());
            map.put("辅导企业情况", expert.getCoachingEnterprises());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    public Map<String, String> douploadpic(MultipartFile multipartFile, Integer id) {
        // 文件大小验证
        FileUtil.checkSize(properties.getAvatarMaxSize(), multipartFile.getSize());
        // 验证文件上传的格式
        String image = "gif jpg png jpeg";
        String fileType = FileUtil.getExtensionName(multipartFile.getOriginalFilename());
        if (fileType != null && !image.contains(fileType)) {
            throw new BadRequestException("文件格式错误！, 仅支持 " + image + " 格式");
        }
        Optional<Expert> res = expertRepository.findById(id);
        if (res.isPresent()) {
            Expert expert = res.orElseGet(() -> new Expert());
            String oldPath = expert.getAvatar();
            File file = FileUtil.upload(multipartFile, properties.getExpert());
            String path = Objects.requireNonNull(file).getPath();
            String[] files = path.split("file");
            res.get().setAvatar("/file" + files[1]);
            expertRepository.save(res.get());
            if (StringUtils.isNotBlank(oldPath)) {
                FileUtil.del(oldPath);
            }
            return new HashMap<String, String>(1) {{
                put("expert", file.getName());
            }};
        }
        return new HashMap<String, String>(1) {{
            put("expert", "fail");
        }};
    }

    /**
     * 生成专家绑定码。绑定码有效时间：1天
     *
     * @param expertId 专家ID
     * @return ExpertBindDto
     */
    public ExpertBindDto generateQrCode(Integer expertId) {
        if (!expertRepository.existsById(expertId)) {
            throw new BadRequestException("专家[id:" + expertId + "]不存在");
        }
        String code = RandomUtil.randomString(10);
        String qrcode = wxClient.generateMpQr(
                null,
                "type=bind&code=" + code
        );
        String url = wxClient.generateUrlLink(
                null,
                "type=bind&code=" + code,
                86400000L
        );
        redisUtils.set("expert:bind:" + code, expertId, 86400);
        ExpertBindDto dto = new ExpertBindDto();
        dto.setExpireTime(86400000L);
        dto.setQrcode(qrcode);
        dto.setUrl(url);
        return dto;
    }

    public ExpertDto findExpertByCode(String code) {
        Integer expertId = (Integer) redisUtils.get("expert:bind:" + code);
        if (expertId == null) {
            throw new BadRequestException("邀请码不存在");
        }
        final Expert expert = expertRepository.findById(expertId).orElseThrow(() ->
                new BadRequestException("专家[id:" + expertId + "]不存在")
        );
        return expertMapper.toDto(expert);
    }

    @Transactional
    public AuthDto bindExpert(ExpertBindDto2 dto, HttpServletRequest request) {
        Integer expertId = (Integer) redisUtils.get("expert:bind:" + dto.getCode());
        if (expertId == null) {
            throw new BadRequestException("邀请码不存在");
        }
        JwtUserDto currentUser;
        try {
            currentUser = userDetailsService.loadUserByUsername(JwtSecurityUtils.getCurrentUsername());
            final Long userId = currentUser.getUser().getId();
            // 若已绑定其他专家，则先取消原先绑定的专家
            Expert e = expertRepository.findByUserId(userId);
            if (e != null) {
                e.setUserId(null);
                expertRepository.save(e);
            }
        } catch (UsernameNotFoundException e) {
            // 用户未登录，则走登录流程
            if (dto.getWxCode() == null) {
                throw new BadRequestException("用户信息未找到");
            }
            WxAuthenticationToken wxAuthentication = authenticationService.authenticateByWxMpCode(dto.getWxCode(), 4);
            currentUser = wxAuthentication.getUser();
        }
        Expert expert = expertRepository.findById(expertId).orElseThrow(() ->
                new BadRequestException("专家[id:" + expertId + "]不存在")
        );
        Long currentUserId = currentUser.getUser().getId();
        expert.setUserId(currentUserId);
        expertRepository.save(expert);
        if (currentUser.getUser().getRoles().stream().noneMatch(s -> s.getId() == 4)) {
            userService.grantRole(currentUserId, 4L);
        }
        redisUtils.del("expert:bind:" + dto.getCode());

        // 权限修改，返回新的token
        User user = userRepository.findByUsername(currentUser.getUsername());
        WxAuthenticationToken authentication = authenticationService.authenticateByUnionId(user.unionId);
        SecurityContextHolder.getContext().setAuthentication(authentication);
        String apiToken = tokenProvider.createToken(authentication);
        JwtUserDto jwtUserDto = authentication.getPrincipal();
        // 保存在线信息
        onlineUserService.save(jwtUserDto, OnlineUser.SYSTEM, apiToken, request);
        // 返回 token 与 用户信息
        AuthDto authDto = new AuthDto(
                securityProperties.getTokenStartWith() + apiToken,
                jwtUserDto
        );
        if (loginProperties.isSingleLogin()) {
            //踢掉之前已经登录的token
            onlineUserService.checkLoginOnUser(authDto.getUser().getUsername(), apiToken);
        }
        return authDto;
    }

    public int findByType(ExpertCountQueryCriteria criteria) {
        //return expertRepository.findByType(criteria.getType());
        return expertRepository.findByXcxType(criteria.getType());
    }

    public List<DictDetailDto> findAllType() {
        DictQueryCriteria dictQueryCriteria = new DictQueryCriteria();
        dictQueryCriteria.setBlurry("expert_type");
        List<DictDto> list = dictService.queryAll(dictQueryCriteria);
        if (list != null && list.size() == 1) {
            return dictDetailService.getDictByDictId(list.get(0).getId());
        }
        return null;
    }

    public void distributionUser(Long userId, int expertId) {
        if (userId == null) {
            throw new BadRequestException("待分配的用户ID未找到");
        }
        Optional<Expert> res = expertRepository.findById(expertId);
        if (!res.isPresent()) {
            throw new BadRequestException("专家未找到");
        }
        UserDto userDto = userService.findById(userId);
        if (userDto == null) {
            throw new BadRequestException("待分配的用户未找到");
        }
        Expert expert = res.get();
        expert.setUserId(userDto.getId());
        expertRepository.save(expert);
    }

    public List<Expert> getExpertInfoByListId(Integer[] expertIds) {
        List<Expert> list = new ArrayList<Expert>();
        if (expertIds == null) {
            throw new BadRequestException("专家ListId未找到");
        }
        for (Integer id : expertIds) {
            Optional<Expert> res = expertRepository.findById(id);
            if (res.isPresent()) {
                list.add(res.get());
            }
        }
        return list;
    }
}